package com.superb.system.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.captcha.generator.MathGenerator;
import cn.hutool.core.math.Calculator;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.superb.common.core.annotation.SuperbDataScope;
import com.superb.common.core.annotation.SuperbRestMapping;
import com.superb.common.core.model.Result;
import com.superb.common.properties.SuperbCustomProperties;
import com.superb.common.redis.key.KeyType;
import com.superb.common.redis.key.RedisKey;
import com.superb.common.redis.utils.RedisUtils;
import com.superb.common.utils.HeardersUtils;
import com.superb.system.api.dto.Token;
import com.superb.system.api.dto.ValidateImage;
import com.superb.system.api.entity.SystemTenant;
import com.superb.system.api.vo.PhoneCodeLogin;
import com.superb.system.api.vo.PwdLogin;
import com.superb.system.service.SystemTenantService;
import com.superb.system.service.SystemUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.time.Duration;
import java.util.List;

/**
 * @Author: ajie
 * @CreateTime: 2024-05-14 09:24
 */
@SuperbDataScope
@Tag(name = "登录管理")
@SuperbRestMapping("admin/login")
@ApiSupport(author = "阿杰：ajie20999@163.com", order = 1)
public class LoginController {

    @Resource
    private SystemUserService userService;

    @Resource
    private SystemTenantService tenantService;

    @Resource
    private SuperbCustomProperties customProperties;
    @ApiOperationSupport(order = 1)
    @GetMapping("validateImage/{type}")
    @Operation(summary = "获取验证码", parameters = {
            @Parameter(name = "type", required = true, description = "验证码类型：random随机字符串、calc计算", in = ParameterIn.PATH),
    })
    public Result<ValidateImage> validateImage(@PathVariable String type) {
        String code;
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 45, 4, 2);
        if (type.equals("calc")) {
            // 四则运算
            captcha.setGenerator(new MathGenerator(1));
            captcha.createCode();
            code = String.valueOf(((int) Calculator.conversion(captcha.getCode())));
        } else {
            code = captcha.getCode().toLowerCase();
        }
        String key = RandomUtil.randomString(16);
        // 验证码默认60s有效期
        RedisKey redisKey = new RedisKey(KeyType.TIME, Duration.ofMinutes(1), key);
        // 存入验证码
        RedisUtils.build().value().set(redisKey, code);
        ValidateImage validateImage = new ValidateImage();
        validateImage.setKey(key);
        validateImage.setData(captcha.getImageBase64Data());

        return Result.success(validateImage);
    }

    @ApiOperationSupport(order = 2)
    @GetMapping("validateCode/{phone}")
    @Operation(summary = "获取手机验证码", parameters = {
            @Parameter(name = "phone", required = true, description = "获取手机号", in = ParameterIn.PATH),
    })
    public Result<ValidateImage> validateCode(@PathVariable String phone) {
        int code = RandomUtil.randomInt(1000, 9999);
        // 验证码默认60s有效期
        RedisKey redisKey = new RedisKey(KeyType.TIME, Duration.ofMinutes(5), "vilidate::" + phone);
        // 存入验证码
        RedisUtils.build().value().set(redisKey, code);
        return Result.success();
    }

    @PostMapping("pwdLogin")
    @ApiOperationSupport(order = 3)
    @Operation(summary = "账号密码登录", description = "系统用户账号密码登录")
    public Result<Token> pwdLogin(@RequestBody @Validated PwdLogin login) {
        return Result.success(userService.pwdLogin(login));
    }

    @PostMapping("phoneCodeLogin")
    @ApiOperationSupport(order = 4)
    @Operation(summary = "手机号验证码登录")
    public Result<Token> phoneCodeLogin(@RequestBody @Validated PhoneCodeLogin login) {
        Token token = userService.phoneCodeLogin(login);
        return Result.success(token);
    }

    @GetMapping("loginOut")
    @ApiOperationSupport(order = 5)
    @Operation(summary = "退出登录")
    public Result<Boolean> loginout() {
        StpUtil.logout(StpUtil.getLoginId(), HeardersUtils.getClientId());
        return Result.success("退出登录成功！");
    }

    @GetMapping("tenantInfo")
    @ApiOperationSupport(order = 6)
    @Operation(summary = "获取租户信息")
    public Result<SystemTenant> info() {
        RedisKey key = new RedisKey(KeyType.PER, "tenantInfo");
        SystemTenant tenant = RedisUtils.build().hash().getNullSet(key, HeardersUtils.getTenantId(), () -> {
            LambdaQueryWrapper<SystemTenant> lqw = new LambdaQueryWrapper<>();
            lqw.eq(SystemTenant::getTenantKey, HeardersUtils.getTenantId());
            return tenantService.getOne(lqw);
        }, utils -> utils.hash().get(key, HeardersUtils.getTenantId()));
        return Result.success(tenant);
    }

    @GetMapping("tenantList")
    @ApiOperationSupport(order = 6)
    @Operation(summary = "获取租户信息")
    public Result<List<SystemTenant>> infoList() {
        RedisKey key = new RedisKey(KeyType.PER, "tenantList");
        List<SystemTenant> list = RedisUtils.build().hash().getNullSet(key, HeardersUtils.getTenantId(), () -> {
            if (customProperties.getBaseTenant().equals(HeardersUtils.getTenantId())) {
                return tenantService.list();
            }
            LambdaQueryWrapper<SystemTenant> lqw = new LambdaQueryWrapper<>();
            lqw.eq(SystemTenant::getTenantKey, HeardersUtils.getTenantId());
            return tenantService.list(lqw);
        }, utils -> utils.hash().get(key, HeardersUtils.getTenantId()));
        return Result.success(list);
    }


    @GetMapping("clearCache")
    @ApiOperationSupport(order = 5)
    @Operation(summary = "清除当前操作人的缓存")
    public Result<Boolean> clearCache() {
        String userId = StpUtil.getLoginId().toString();
        RedisKey key = new RedisKey(KeyType.TIME,"userCache:" + userId);
        RedisKey key1 = new RedisKey(KeyType.TIME,"user:" + userId);
        RedisKey key3 = new RedisKey(KeyType.PER,"menuCache:" + userId);
        // 用户部门列表和数据权限列表
        RedisKey key4 = new RedisKey(KeyType.TIME,"organizationIds:" + HeardersUtils.getOrganId());
        RedisKey key5 = new RedisKey(KeyType.TIME,"organization:" + HeardersUtils.getOrganId());
        RedisKey key2 = new RedisKey(KeyType.PER,"userInfo:" + userId + "*");
        RedisUtils.build().del(key, key1, key2, key3, key4, key5);
        RedisUtils.build().dels(key2);
        return Result.success();
    }

}
